package owl2vowl.model.data;

import owl2vowl.model.data.VowlData;
import owl2vowl.model.data.VowlGenerator;
import owl2vowl.model.data.VowlSearcher;
import owl2vowl.model.entities.nodes.AbstractNode;
import owl2vowl.model.entities.nodes.classes.VowlThing;
import owl2vowl.model.entities.properties.AbstractProperty;
import java.util.Iterator;
import org.semanticweb.owlapi.model.IRI;

public class VowlThingProvider {
	private final VowlData vowlData;
	private final VowlSearcher searcher;
	private final VowlGenerator generator;

	public VowlThingProvider(VowlData vowlData, VowlSearcher searcher, VowlGenerator generator) {
		this.vowlData = vowlData;
		this.searcher = searcher;
		this.generator = generator;
	}

	public VowlThing getConnectedThing(IRI nodeIri) {
		AbstractNode node = this.vowlData.getNodeForIri(nodeIri);
		Iterator arg2 = node.getOutGoingProperties().iterator();

		IRI out;
		AbstractProperty prop;
		AbstractNode domainNode;
		while (arg2.hasNext()) {
			out = (IRI) arg2.next();
			prop = this.vowlData.getPropertyForIri(out);
			if (prop.getRanges().size() == 1) {
				domainNode = this.vowlData.getNodeForIri((IRI) prop.getRanges().iterator().next());
				if (domainNode.getType().equals("owl:Thing")) {
					return (VowlThing) domainNode;
				}
			}
		}

		arg2 = node.getInGoingProperties().iterator();

		while (arg2.hasNext()) {
			out = (IRI) arg2.next();
			prop = this.vowlData.getPropertyForIri(out);
			if (prop.getDomains().size() == 1) {
				domainNode = this.vowlData.getNodeForIri((IRI) prop.getDomains().iterator().next());
				if (domainNode.getType().equals("owl:Thing")) {
					return (VowlThing) domainNode;
				}
			}
		}

		return null;
	}

	public boolean containsConnectedThing(IRI nodeIri1, IRI nodeIri2) {
		AbstractNode node1 = this.vowlData.getNodeForIri(nodeIri1);
		AbstractNode node2 = this.vowlData.getNodeForIri(nodeIri2);
		Iterator arg4 = node1.getOutGoingProperties().iterator();

		IRI out;
		AbstractProperty prop;
		AbstractNode domainNode;
		while (arg4.hasNext()) {
			out = (IRI) arg4.next();
			prop = this.vowlData.getPropertyForIri(out);
			if (prop.getRanges().size() == 1) {
				domainNode = this.vowlData.getNodeForIri((IRI) prop.getRanges().iterator().next());
				if (domainNode.getType().equals("owl:Thing") && domainNode == node2) {
					return true;
				}
			}
		}

		arg4 = node1.getInGoingProperties().iterator();

		while (arg4.hasNext()) {
			out = (IRI) arg4.next();
			prop = this.vowlData.getPropertyForIri(out);
			if (prop.getDomains().size() == 1) {
				domainNode = this.vowlData.getNodeForIri((IRI) prop.getDomains().iterator().next());
				if (domainNode.getType().equals("owl:Thing") && domainNode == node2) {
					return true;
				}
			}
		}

		return false;
	}

	public boolean isFree(VowlThing thing) {
		Iterator arg1 = thing.getOutGoingProperties().iterator();

		boolean allowed;
		do {
			AbstractProperty property;
			AbstractNode domainNode;
			do {
				IRI out;
				if (!arg1.hasNext()) {
					arg1 = thing.getInGoingProperties().iterator();

					do {
						do {
							if (!arg1.hasNext()) {
								return true;
							}

							out = (IRI) arg1.next();
							property = this.vowlData.getPropertyForIri(out);
						} while (property.getDomains().size() != 1);

						domainNode = this.vowlData.getNodeForIri((IRI) property.getDomains().iterator().next());
						allowed = domainNode.getType().equals("rdfs:Datatype")
								|| domainNode.getType().equals("rdfs:Literal")
								|| domainNode.getType().equals("owl:Thing");
					} while (allowed);

					return false;
				}

				out = (IRI) arg1.next();
				property = this.vowlData.getPropertyForIri(out);
			} while (property.getRanges().size() != 1);

			domainNode = this.vowlData.getNodeForIri((IRI) property.getRanges().iterator().next());
			allowed = domainNode.getType().equals("rdfs:Datatype") || domainNode.getType().equals("rdfs:Literal")
					|| domainNode.getType().equals("owl:Thing");
		} while (allowed);

		return false;
	}

	public VowlThing getDisconnectedThing() {
		Iterator arg0 = this.searcher.getThings().iterator();

		VowlThing thing;
		do {
			if (!arg0.hasNext()) {
				return this.generator.generateThing();
			}

			thing = (VowlThing) arg0.next();
		} while (!this.isFree(thing));

		return thing;
	}
}